import config from '../config/config.js'
import {
	getToken,
	removeToken
} from '@/utils/auth'
import errorCode from '@/utils/errorCode'
import {
	toast,
	showConfirm,
	tansParams
} from '@/utils/common'

const DEFAULT_TIMEOUT = 10000
const BASE_URL = config.baseUrl

// 错误消息映射
const ERROR_MESSAGE_MAP = {
	'request:fail ': '网络异常',
	'request:fail timeout': '网络超时',
	'Request failed with status code': '网络请求失败'
}

// 处理登录过期
const handleTokenExpired = async () => {
	toast('登录状态已过期')
	const confirm = await showConfirm('登录状态已过期，请重新登录?')
	if (confirm) {
		removeToken()
		const pages = getCurrentPages()
		const currentRoute = pages[pages.length - 1].route
		const navigateMethod = currentRoute === 'pages/index/index' ? 'redirectTo' : 'navigateTo'
		uni[navigateMethod]({
			url: '/pages/index/index'
		})
	}
}

// 处理响应错误
const handleResponseError = (code, msg) => {
	const errorMsg = errorCode[code] || msg || errorCode['default']

	if (code === 401) {
		handleTokenExpired()
		return Promise.reject('请重新登录')
	}
	if (code === 404) {
		toast(errorMsg || "资源不存在")
		return Promise.reject('资源不存在')
	}

	if (code === 500) {
		toast(errorMsg)
		return Promise.reject('服务器错误')
	}

	if (code !== 200) {
		toast(errorMsg || '数据异常')
		return Promise.reject(code)
	}
}

// 处理网络错误
const handleNetworkError = (error) => {
	let {
		errMsg
	} = error
	const matchedKey = Object.keys(ERROR_MESSAGE_MAP).filter(key => errMsg == key)
	errMsg = matchedKey ? ERROR_MESSAGE_MAP[matchedKey] : errMsg

	toast(errMsg)
	return Promise.reject(errMsg)
}

// 构建请求配置
const buildRequestConfig = (config) => {
	const {
		headers = {}, method = 'get', params, data, url
	} = config

	// 设置token
	if (getToken() && headers.isToken !== false) {
		headers['Authorization'] = `Bearer ${getToken()}`
	}

	// 处理GET参数
	let requestUrl = url
	if (params && method.toLowerCase() === 'get') {
		const queryString = tansParams(params)
		requestUrl = `${url}?${queryString}`.replace(/&$/, '')
	}

	return {
		method,
		timeout: config.timeout || DEFAULT_TIMEOUT,
		url: config.baseUrl || BASE_URL + requestUrl,
		data,
		header: headers,
		dataType: 'json'
	}
}

const request = (config) => {
	const requestConfig = buildRequestConfig(config)

	return uni.request(requestConfig)
		.then(response => {
			const {
				code = 200, msg
			} = response.data

			if (code !== 200) {
				return handleResponseError(code, msg)
			}

			return response.data
		})
		.catch(handleNetworkError)
}

export default request